﻿Imports System.IO

Public Class Form1


    'Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    '    DataGridView1.AllowUserToAddRows = False
    '    Dim ColumnTag As String = ""
    '    DataGridView1.Rows.Clear()
    '    CheckBox2.Checked = False
    '    DoCancel = False
    '    ReDim sortOrder(DataGridView1.Columns.Count)
    '    For Each bl As Boolean In sortOrder
    '        bl = False
    '    Next

    '    Dim CurrentLevel As Integer = 0
    '    For Each Drive As System.IO.DriveInfo In My.Computer.FileSystem.Drives
    '        If Not (Drive.Name.Contains("F")) Then Continue For
    '        ColumnTag = Drive.Name.Replace(":\", "")
    '        Dim index As Integer = 0
    '        Try
    '            Dim ChildCount As Integer = 0
    '            For Each Directory As System.IO.DirectoryInfo In Drive.RootDirectory.GetDirectories()
    '                Dim dirDetails As DirDetails
    '                ChildCount += 1
    '                Dim ParentPath = Drive.Name
    '                dirDetails = GetDirectoryInfo(Drive.Name.Replace(":\", "").Trim(), ParentPath, Directory, ColumnTag, ChildCount, index, CurrentLevel)
    '            Next
    '        Catch
    '        End Try
    '        Exit For
    '    Next
    'End Sub

    Public Class DirDetails
        Public FileCount As ULong = 0
        Public DirsCount As ULong = 0
        Public StorageSize As ULong = 0
        Public RowTag As String = ""
        Public Sub Add(temp As DirDetails)
            FileCount += temp.FileCount
            DirsCount += temp.DirsCount
            StorageSize += temp.StorageSize
        End Sub
    End Class

 
    Private Sub MaxShowDepth_ValueChanged(sender As Object, e As EventArgs) Handles MaxShowDepth.ValueChanged

        For RowIndex = 0 To DataGridView1.Rows.Count - 1
            'Dim cells As DataGridViewCellCollection = DataGridView1.Rows(RowIndex).Cells
            Dim levelStr
            Try
                levelStr = DataGridView1.Rows(RowIndex).Cells("DirLevel").Value.ToString()
            Catch
                Continue For
            End Try

            Dim lev As Integer
            Dim res As Boolean = Integer.TryParse(levelStr, lev)

            If (Not res) Then Return

            If (lev > (MaxShowDepth.Value)) Then
                DataGridView1.Rows(RowIndex).Visible = False
            Else
                DataGridView1.Rows(RowIndex).Visible = True
            End If
        Next
    End Sub





    Dim sortOrder() As Boolean
    Private Sub DataGridView1_ColumnHeaderMouseClick(sender As Object, e As DataGridViewCellMouseEventArgs) Handles DataGridView1.ColumnHeaderMouseClick
        If (e.ColumnIndex = DataGridView1.Columns("StorageSize").Index) Then
            Dim sortedRowsList As DataGridViewRow()
            If (Not sortOrder(DataGridView1.Columns("StorageSize").Index)) Then
                Dim sortedRows1 = From w As DataGridViewRow In DataGridView1.Rows Where (Not w.Cells("RowPath") Is Nothing) Order By ToInt(w.Cells(DataGridView1.Columns("StorageSize").Index).Value) Descending
                sortedRowsList = sortedRows1.ToArray()
            Else
                Dim sortedRows2 = From w As DataGridViewRow In DataGridView1.Rows Where (Not w.Cells("RowPath") Is Nothing) Order By ToInt(w.Cells(DataGridView1.Columns("StorageSize").Index).Value)
                sortedRowsList = sortedRows2.ToArray()
            End If
            sortOrder(DataGridView1.Columns("StorageSize").Index) = Not sortOrder(DataGridView1.Columns("StorageSize").Index)

            DataGridView1.Rows.Clear()
            DataGridView1.Rows.AddRange(sortedRowsList)
        ElseIf (e.ColumnIndex = DataGridView1.Columns("FileCount").Index) Then
            Dim sortedRowsList As DataGridViewRow()
            If (Not sortOrder(DataGridView1.Columns("FileCount").Index)) Then
                Dim sortedRows1 = From w As DataGridViewRow In DataGridView1.Rows Where (Not w.Cells("RowPath") Is Nothing) Order By ToInt(w.Cells(DataGridView1.Columns("FileCount").Index).Value) Descending
                sortedRowsList = sortedRows1.ToArray()
            Else
                Dim sortedRows2 = From w As DataGridViewRow In DataGridView1.Rows Where (Not w.Cells("RowPath") Is Nothing) Order By ToInt(w.Cells(DataGridView1.Columns("FileCount").Index).Value)
                sortedRowsList = sortedRows2.ToArray()
            End If
            sortOrder(DataGridView1.Columns("FileCount").Index) = Not sortOrder(DataGridView1.Columns("FileCount").Index)

            DataGridView1.Rows.Clear()
            DataGridView1.Rows.AddRange(sortedRowsList)
        ElseIf (e.ColumnIndex = DataGridView1.Columns("DirLevel").Index) Then
            Dim sortedRowsList As DataGridViewRow()
            If (Not sortOrder(DataGridView1.Columns("DirLevel").Index)) Then
                Dim sortedRows1 = From w As DataGridViewRow In DataGridView1.Rows Where (Not w.Cells("RowPath") Is Nothing) Order By ToInt(w.Cells(DataGridView1.Columns("DirLevel").Index).Value) Descending Order By ToInt(w.Cells(DataGridView1.Columns("DirIndex").Index).Value) Descending
                sortedRowsList = sortedRows1.ToArray()
            Else
                Dim sortedRows2 = From w As DataGridViewRow In DataGridView1.Rows Where (Not w.Cells("RowPath") Is Nothing) Order By ToInt(w.Cells(DataGridView1.Columns("DirLevel").Index).Value) Order By ToInt(w.Cells(DataGridView1.Columns("DirIndex").Index).Value)
                sortedRowsList = sortedRows2.ToArray()
            End If
            sortOrder(DataGridView1.Columns("DirLevel").Index) = Not sortOrder(DataGridView1.Columns("DirLevel").Index)

            DataGridView1.Rows.Clear()
            DataGridView1.Rows.AddRange(sortedRowsList)

        End If
    End Sub

    Private Function ToInt(strn As String) As Long

        Dim val As Long = 0
        If strn Is Nothing Then Return Long.MaxValue
        Dim res As Boolean = Long.TryParse(strn, val)
        Return val
    End Function

    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' The following is obsolete but left in as a further Linq-DataGridView query example
    ' It was meant to display different header text when Drives were first displayed
    ' The drive info just reused Directory columns, rather than have separate columns
    '
    'Dim foldersHeader() As String
    'Dim drivesHeader() As String
    '
    'Private Sub SetDriversHeaderText()
    '    'Get current headers
    '    Dim var = From w As DataGridViewColumn In DataGridView1.Columns Select w.HeaderText
    '    foldersHeader = var.ToArray()

    '    'Set custom header text when drives only are shown
    '    drivesHeader = var.ToArray()
    '    drivesHeader(6) = "Size"
    '    drivesHeader(7) = "FreeSpace"
    '    drivesHeader(8) = "%Free"
    '    drivesHeader(9) = "Format"

    '    For i As Integer = 0 To DataGridView1.Columns.Count - 1
    '        DataGridView1.Columns(i).HeaderText = drivesHeader(i)
    '    Next
    'End Sub
    '
    'Private Sub RestorFoldersHeaderText()
    '    For i As Integer = 0 To DataGridView1.Columns.Count - 1
    '        DataGridView1.Columns(i).HeaderText = foldersHeader(i)
    '    Next
    'End Sub
    ''' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''



    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Me.Top = 1
        Me.Left = 1
        GetDrives()
    End Sub






    Dim CurrentlevelfromUI As Integer = 0
    Private Sub DataGridView1_CellDoubleClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellDoubleClick

        Dim row As Integer = e.RowIndex
        'Check if header 
        If (row = -1) Then Return
        DataGridView1.Rows(row).Selected = False
        Dim ParentPath As String = DataGridView1.Rows(row).Cells("RowPath").Value
        If (DataGridView1.Rows(row).Cells("DriveSize").Value = "") Then
            If (DataGridView1.Rows(row).Cells("DirLevel").Value = "1") Then
                'A Subdirectory
                Dim subDirPath As String = DataGridView1.Rows(row).Cells("RowPath").Value
                Dim subDirDriveLetter = DataGridView1.Rows(row).Cells("Drive").Value
                Dim subDirLevel = DataGridView1.Rows(row).Cells("DirLevel").Value

                CurrentlevelfromUI = subDirLevel

                'Make inactive if no subdirectories
                Dim subDirCount As Integer = DataGridView1.Rows(row).Cells("DirectoryCount").Value
                If (subDirCount = 0) Then
                    Beep()
                    Return
                End If



                If (DataGridView1.Rows(row).Cells("RowState").Value = RowDataStates.Uninitiated.ToString()) Then
                    'Generate Subfolder Data
                    Dim Path As String = DataGridView1.Rows(row).Cells("RowPath").Value
                    DataGridView1.Refresh()
                    GetDrive_LowerLevelDirs(DataGridView1.Rows(row))
                    Dim var = From w As DataGridViewRow In DataGridView1.Rows Select w Where (w.Cells("ParentPath").Value.Contains(ParentPath))
                    Dim subFolders() As DataGridViewRow = var.ToArray()
                    For Each subrow As DataGridViewRow In subFolders
                        subrow.Visible = False
                        subrow.Cells("RowState").Value = RowDataStates.Hidden.ToString()

                    Next
                    var = From w As DataGridViewRow In DataGridView1.Rows Select w Where (w.Cells("ParentPath").Value = ParentPath)
                    DataGridView1.Rows(row).DefaultCellStyle.ForeColor = LevelActiveForeColor(subDirLevel)
                    DataGridView1.Rows(row).DefaultCellStyle.BackColor = LevelActiveBackColor(subDirLevel)
                    DataGridView1.Refresh()
                    subFolders = var.ToArray()
                    For Each subrow As DataGridViewRow In subFolders
                        subrow.Visible = True
                        subrow.DefaultCellStyle.BackColor = SubLevelActiveBackColor(subDirLevel)
                        subrow.DefaultCellStyle.ForeColor = SubLevelActiveForeColor(subDirLevel)
                        subrow.Cells("Nav").Value = subrow.Cells("Nav").Value.Replace("+-|", "|")

                    Next
                    DataGridView1.Rows(row).Cells("RowState").Value = RowDataStates.Visible.ToString()
                    DataGridView1.Rows(row).Cells("Nav").Value = DataGridView1.Rows(row).Cells("Nav").Value.Replace("|", "+-|")
                ElseIf (DataGridView1.Rows(row).Cells("RowState").Value = RowDataStates.Visible.ToString()) Then
                    'Hide rows
                    Dim var = From w As DataGridViewRow In DataGridView1.Rows Select w Where (w.Cells("ParentPath").Value.Contains(ParentPath))
                    Dim subFolders() As DataGridViewRow = var.ToArray()
                    For Each subrow As DataGridViewRow In subFolders
                        subrow.Visible = False
                        subrow.Cells("RowState").Value = RowDataStates.Hidden.ToString()

                    Next
                    DataGridView1.Rows(row).Cells("RowState").Value = RowDataStates.Hidden.ToString()
                    DataGridView1.Rows(row).DefaultCellStyle.ForeColor = SubLevelActiveForeColor(subDirLevel - 1)
                    DataGridView1.Rows(row).DefaultCellStyle.BackColor = SubLevelActiveBackColor(subDirLevel - 1)
                    DataGridView1.Rows(row).Cells("Nav").Value = DataGridView1.Rows(row).Cells("Nav").Value.Replace("+-|", "|")

                ElseIf (DataGridView1.Rows(row).Cells("RowState").Value = RowDataStates.Hidden.ToString()) Then
                    'Show rows
                    Dim var = From w As DataGridViewRow In DataGridView1.Rows Select w Where (w.Cells("ParentPath").Value = ParentPath)
                    DataGridView1.Rows(row).DefaultCellStyle.ForeColor = LevelActiveForeColor(subDirLevel)
                    DataGridView1.Rows(row).DefaultCellStyle.BackColor = LevelActiveBackColor(subDirLevel)
                    DataGridView1.Refresh()
                    Dim subFolders() As DataGridViewRow = var.ToArray()
                    For Each subrow As DataGridViewRow In subFolders
                        subrow.Visible = True
                        subrow.DefaultCellStyle.BackColor = SubLevelActiveBackColor(subDirLevel)
                        subrow.DefaultCellStyle.ForeColor = SubLevelActiveForeColor(subDirLevel)
                        subrow.Cells("Nav").Value = subrow.Cells("Nav").Value.Replace("+-|", "|")

                    Next
                    DataGridView1.Rows(row).Cells("RowState").Value = RowDataStates.Visible.ToString()
                    DataGridView1.Rows(row).Cells("Nav").Value = DataGridView1.Rows(row).Cells("Nav").Value.Replace("|", "+-|")

                End If

            Else
                'A Subdirectory
                'Make inactive if no subdirectories
                Dim subDirCount As Integer = DataGridView1.Rows(row).Cells("DirectoryCount").Value
                If (subDirCount = 0) Then
                    Beep()
                    Return
                End If

                Dim subDirPath As String = DataGridView1.Rows(row).Cells("RowPath").Value
                Dim subDirDriveLetter = DataGridView1.Rows(row).Cells("Drive").Value
                Dim subDirLevel = DataGridView1.Rows(row).Cells("DirLevel").Value


                If (DataGridView1.Rows(row).Cells("RowState").Value = RowDataStates.Visible.ToString()) Then
                    'Hide rows
                    Dim var = From w As DataGridViewRow In DataGridView1.Rows Select w Where (w.Cells("ParentPath").Value.Contains(ParentPath))
                    Dim subFolders() As DataGridViewRow = var.ToArray()
                    For Each subrow As DataGridViewRow In subFolders
                        subrow.Visible = False
                        subrow.Cells("RowState").Value = RowDataStates.Hidden.ToString()

                    Next
                    DataGridView1.Rows(row).Cells("RowState").Value = RowDataStates.Hidden.ToString()
                    DataGridView1.Rows(row).DefaultCellStyle.ForeColor = SubLevelActiveForeColor(subDirLevel - 1)
                    DataGridView1.Rows(row).DefaultCellStyle.BackColor = SubLevelActiveBackColor(subDirLevel - 1)
                    DataGridView1.Rows(row).Cells("Nav").Value = DataGridView1.Rows(row).Cells("Nav").Value.Replace("+-|", "|")

                ElseIf (DataGridView1.Rows(row).Cells("RowState").Value = RowDataStates.Hidden.ToString()) Then
                    'Show rows
                    Dim var = From w As DataGridViewRow In DataGridView1.Rows Select w Where (w.Cells("ParentPath").Value = ParentPath)
                    DataGridView1.Rows(row).DefaultCellStyle.ForeColor = LevelActiveForeColor(subDirLevel)
                    DataGridView1.Rows(row).DefaultCellStyle.BackColor = LevelActiveBackColor(subDirLevel)
                    DataGridView1.Refresh()
                    Dim subFolders() As DataGridViewRow = var.ToArray()
                    For Each subrow As DataGridViewRow In subFolders
                        subrow.Visible = True
                        subrow.DefaultCellStyle.BackColor = SubLevelActiveBackColor(subDirLevel)
                        subrow.DefaultCellStyle.ForeColor = SubLevelActiveForeColor(subDirLevel)
                        subrow.Cells("Nav").Value = subrow.Cells("Nav").Value.Replace("+-|", "|")

                    Next
                    DataGridView1.Rows(row).Cells("RowState").Value = RowDataStates.Visible.ToString()
                    DataGridView1.Rows(row).Cells("Nav").Value = DataGridView1.Rows(row).Cells("Nav").Value.Replace("|", "+-|")

                End If
            End If
        Else
            'A Drive
            Dim drivePath As String = DataGridView1.Rows(row).Cells("RowPath").Value
            Dim DriveLetter = DataGridView1.Rows(row).Cells("Drive").Value
            Dim ColTag As String = DataGridView1.Rows(row).Cells("RowTag").Value
            If (DataGridView1.Rows(row).Cells("RowState").Value = RowDataStates.Uninitiated.ToString()) Then
                'Generate Subfolder Data
                For Each Drive As System.IO.DriveInfo In My.Computer.FileSystem.Drives

                    If (Drive.Name = drivePath) Then
                        DataGridView1.Rows(row).DefaultCellStyle.ForeColor = DriveActiveForeColor
                        DataGridView1.Rows(row).DefaultCellStyle.BackColor = DriveActiveBackColor
                        DataGridView1.Refresh()
                        Get_Drive_FirstLevelDirs(Drive, ColTag)
                        Exit For
                    End If
                Next
                DataGridView1.Rows(row).Cells("RowState").Value = RowDataStates.Visible.ToString()
                DataGridView1.Rows(row).Cells("Nav").Value = DataGridView1.Rows(row).Cells("Nav").Value.Replace("|", "+-|")
            ElseIf (DataGridView1.Rows(row).Cells("RowState").Value = RowDataStates.Visible.ToString()) Then
                'Hide rows
                For Each Drive As System.IO.DriveInfo In My.Computer.FileSystem.Drives
                    If (Drive.Name = drivePath) Then
                        Dim var = From w As DataGridViewRow In DataGridView1.Rows Select w Where ((w.Cells("Drive").Value = DriveLetter) And (w.Cells("DirLevel").Value <> 0))
                        Dim subFolders() As DataGridViewRow = var.ToArray()
                        For Each subrow1 As DataGridViewRow In subFolders
                            subrow1.Visible = False
                            subrow1.Cells("RowState").Value = RowDataStates.Hidden.ToString()
                            subrow1.Cells("Nav").Value = subrow1.Cells("Nav").Value.Replace("+-|", "|")

                        Next
                        Exit For
                    End If
                Next

                DataGridView1.Rows(row).Cells("RowState").Value = RowDataStates.Hidden.ToString()
                DataGridView1.Rows(row).DefaultCellStyle.ForeColor = DriveInActiveForeColor
                DataGridView1.Rows(row).DefaultCellStyle.BackColor = DriveInActiveBackColor
                DataGridView1.Rows(row).Cells("Nav").Value = DataGridView1.Rows(row).Cells("Nav").Value.Replace("+-|", "|")
            ElseIf (DataGridView1.Rows(row).Cells("RowState").Value = RowDataStates.Hidden.ToString()) Then
                'Show rows
                DataGridView1.Rows(row).DefaultCellStyle.ForeColor = DriveActiveForeColor
                DataGridView1.Rows(row).DefaultCellStyle.BackColor = DriveActiveBackColor
                DataGridView1.Refresh()
                For Each Drive As System.IO.DriveInfo In My.Computer.FileSystem.Drives
                    If (Drive.Name = drivePath) Then
                        Dim var = From w As DataGridViewRow In DataGridView1.Rows Select w Where ((w.Cells("Drive").Value = DriveLetter) And (w.Cells("DirLevel").Value = 1))
                        Dim subFolders() As DataGridViewRow = var.ToArray()
                        For Each subrow As DataGridViewRow In subFolders
                            subrow.Visible = True
                        Next
                        Exit For
                    End If
                Next
                DataGridView1.Rows(row).Cells("RowState").Value = RowDataStates.Visible.ToString()
                DataGridView1.Rows(row).Cells("Nav").Value = DataGridView1.Rows(row).Cells("Nav").Value.Replace("|", "+-|")


            End If
        End If
        DataGridView1.Rows(row).Selected = False
        DataGridView1.Refresh()
        DataGridView1_Sort()
        AutoResize(True)

    End Sub

    Dim FormIsLoading As Boolean = True

    ''' <summary>
    ''' Get Drive Information for all drives
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub GetDrives()

        FormIsLoading = True
        RadioButton1.PerformClick()
        SetMode(Modes.All)
        CurrentlevelfromUI = 0
        DataGridView1.ClearSelection()
        DataGridView1.AllowUserToAddRows = False
        DataGridView1.MultiSelect = False
        DataGridView1.ReadOnly = True

        Dim ColumnTag As String = ""
        DataGridView1.Rows.Clear()

        ReDim sortOrder(DataGridView1.Columns.Count)
        For Each bl As Boolean In sortOrder
            bl = False
        Next
        Dim index As Integer = 0
        DataGridView1.Columns("Nav").DefaultCellStyle.Font = New Font("Courier New", 10)
        For Each Drive As System.IO.DriveInfo In My.Computer.FileSystem.Drives
            ColumnTag = Drive.Name.Replace(":\", "")

            Try
                Dim OneMeg As Long = 1024 * 1024
                Dim OneK As Long = 1024
                Dim TotalSize As Long = Drive.TotalSize / OneMeg
                Dim TotalSizeGig = TotalSize / OneK

                Dim TotalFreeSpace As Long = Drive.TotalFreeSpace / OneMeg
                Dim TotalFreeSpaceGig = TotalFreeSpace / OneK
                Dim PecentFree = TotalFreeSpace * 100 / TotalSize
                Dim dd As String() = New String() {"\", 0, Drive.Name, "", RowAccessStates.OK.ToString(), RowDataStates.Uninitiated.ToString(), Drive.VolumeLabel, TotalSizeGig.ToString("F1") + " G", TotalFreeSpaceGig.ToString("F1") + " G", PecentFree.ToString("F1") + "%", Drive.DriveFormat, Drive.Name.Replace(":\", "").Trim(), "", "", index.ToString(), "0." + index.ToString()}
                LastRow = DataGridView1.Rows.Add(dd)
                index += 1

                'Max finds to zero mean get all
                If Not MaxFinds.Value = 0 Then
                    If index > (MaxFinds.Value - 1) Then Exit For
                End If
            Catch Ex As Exception
                If (Not Ex.Message.Contains("The device is not ready")) Then 'Ignore Empty DVD etc.
                    MessageBox.Show("Error: Loc 1.1 Level 0" + " Drive " + Drive.Name, "FileSystemExplorer", MessageBoxButtons.OK, MessageBoxIcon.Error)
                End If
            End Try

        Next
        DataGridView1_Sort()
        AutoResize(True)
        'My.Computer.Screen.WorkingArea.Width
        FormIsLoading = False

    End Sub

    ''' <summary>
    ''' Called when a drive is first double clicked to get first level folders
    ''' </summary>
    ''' <param name="Drive"></param>
    ''' <remarks></remarks>
    Private Sub Get_Drive_FirstLevelDirs(Drive As System.IO.DriveInfo, ColumnTag As String)
        'DataGridView1.Rows.Clear()
        CurrentlevelfromUI = 1
        'Dim ColumnTag As String = Drive.Name.Replace(":\", "")
        Dim index As Integer = 0
        Dim L1Dir As String = ""
        Try
            Dim ChildCount As Integer = 0
            Dim stack As New Stack(Of Integer)
            stack.Push(MaxDepth.Value)
            MaxDepth.Value = 1
            stack.Push(MaxShowDepth.Value)
            MaxShowDepth.Value = 1
            Dim CurrentLevel As Integer = 0

            Dim TopLevelDirsMask As String = txtTopLevelDirsMask.Text
            'If mask is blank then make *
            If (TopLevelDirsMask = "") Then TopLevelDirsMask = "*"
            'If Mask doesn't any have wildstars or double quotes then append then  * That way 
            If Not (TopLevelDirsMask.Contains("*") Or TopLevelDirsMask.Contains("?") Or TopLevelDirsMask.Contains("""")) Then TopLevelDirsMask += "*"
            'If Mask has " then remove them now. That way can just search for a specific dir but must be in double  quotes
            If TopLevelDirsMask.Contains("""") Then TopLevelDirsMask = TopLevelDirsMask.Replace("""", "")

            For Each L1Directory As System.IO.DirectoryInfo In Drive.RootDirectory.GetDirectories(TopLevelDirsMask, SearchOption.TopDirectoryOnly)
                L1Dir = L1Directory.Name
                Dim dirDetails As DirDetails
                ChildCount += 1
                Dim ParentPath = Drive.Name
                dirDetails = GetDirectoryInfo(Drive.Name.Replace(":\", "").Trim(), ParentPath, L1Directory, ColumnTag, ChildCount, index, CurrentLevel)
                DataGridView1.Rows(LastRow).DefaultCellStyle.ForeColor = SubLevelActiveForeColor(0)
                DataGridView1.Rows(LastRow).DefaultCellStyle.BackColor = SubLevelActiveBackColor(0)
                DataGridView1.Sort(DataGridView1.Columns("RowTag"), System.ComponentModel.ListSortDirection.Ascending)
                Me.Refresh()

                'MaxFinds finds to zero mean get all first level directories
                If Not MaxFinds.Value = 0 Then
                    If ChildCount > (MaxFinds.Value - 1) Then Exit For
                End If
            Next
            MaxShowDepth.Value = stack.Pop()
            MaxDepth.Value = stack.Pop()

        Catch
            MessageBox.Show("Error: Loc 1.2 Level " + 1.ToString() + " Directory " + L1Dir, "FileSystemExplorer", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try

    End Sub

    ''' <summary>
    ''' Called when a first level folder of a drive is double clicked
    ''' </summary>
    ''' <param name="row"></param>
    ''' <remarks></remarks>
    Private Sub GetDrive_LowerLevelDirs(row As DataGridViewRow)
        Dim Path As String = ""
        Try
            Dim ChildCount As Integer = 0

            'ChildCount += 1
            Path = row.Cells("RowPath").Value
            Dim driveLetter As String = row.Cells("Drive").Value
            Dim columnTag As String = row.Cells("RowTag").Value
            Dim index As Integer = row.Cells("DirIndex").Value
            Dim directoryInfLevel1 As DirectoryInfo = My.Computer.FileSystem.GetDirectoryInfo(Path)
            Dim CurrentLevel As Integer = row.Cells("DirLevel").Value
            Me.Refresh()

            Dim DirsMask As String = txtDirsMask.Text
            'If mask is blank then make *
            If (DirsMask = "") Then DirsMask = "*"
            'If Mask doesn't any have wildstars or double quotes then append then  * That way 
            If Not (DirsMask.Contains("*") Or DirsMask.Contains("?") Or DirsMask.Contains("""")) Then DirsMask += "*"
            'If Mask has " then remove them now. That way can just search for a specific dir but must be in double  quotes
            If DirsMask.Contains("""") Then DirsMask = DirsMask.Replace("""", "")

            For Each Directory As System.IO.DirectoryInfo In directoryInfLevel1.GetDirectories(DirsMask, SearchOption.TopDirectoryOnly)
                Dim dirDetails As DirDetails
                ChildCount += 1
                Dim ParentPath = Path
                dirDetails = GetDirectoryInfo(driveLetter, ParentPath, Directory, columnTag, ChildCount, index, CurrentLevel)
                DataGridView1.Rows(LastRow).DefaultCellStyle.ForeColor = SubLevelActiveForeColor(CurrentLevel)
                DataGridView1.Rows(LastRow).DefaultCellStyle.BackColor = SubLevelActiveBackColor(CurrentLevel)
                DataGridView1.Rows(LastRow).Visible = True
                Me.Refresh()
                'ChildCount += 1
                'If Not MaxFinds.Value = 0 Then
                '    If ChildCount > (MaxFinds.Value - 1) Then Exit For
                'End If
            Next
        Catch
            MessageBox.Show("Error: Loc 1.3 Level " + 2.ToString() + " Directory " + Path, "FileSystemExplorer", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try

    End Sub


    Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
        GetDrives()
    End Sub


    Private Sub RadioButton1_CheckedChanged(sender As Object, e As EventArgs) Handles RadioButton3.CheckedChanged, RadioButton2.CheckedChanged, RadioButton1.CheckedChanged, RadioButton4.CheckedChanged
        If Not FormIsLoading Then
            Dim rb As RadioButton = sender
            Dim index As String = rb.Name.Replace("RadioButton", "")
            Select Case index
                Case "1"
                    If RadioButton1.Checked Then
                        SetMode(Modes.All)
                    End If

                Case "2"
                    If RadioButton2.Checked Then
                        SetMode(Modes.Folders)
                    End If

                Case "3"
                    If RadioButton3.Checked Then
                        SetMode(Modes.Drives)
                    End If
                Case "4"
                    If RadioButton4.Checked Then
                        SetMode(Modes.Debug)
                    End If
            End Select
        End If
        AutoResize(False)
    End Sub

    Private Sub AutoResize(doheight As Boolean)
        'Width = DataGridView1.Width

        Dim dgv_width As Integer = DataGridView1.Columns.GetColumnsWidth(DataGridViewElementStates.Visible)
        Dim dgv_height As Integer = DataGridView1.Rows.GetRowsHeight(DataGridViewElementStates.Visible)
        dgv_width += 60
        dgv_height += 220
        If dgv_width <= My.Computer.Screen.WorkingArea.Width Then Me.Width = dgv_width
        If doheight And (dgv_height <= My.Computer.Screen.WorkingArea.Height) Then Me.Height = dgv_height

    End Sub

    Private Sub DataGridView1_RowsAdded(sender As Object, e As DataGridViewRowsAddedEventArgs) Handles DataGridView1.RowsAdded
        AutoResize(True)
    End Sub

    Private Sub DataGridView1_RowsRemoved(sender As Object, e As DataGridViewRowsRemovedEventArgs) Handles DataGridView1.RowsRemoved
        AutoResize(True)
    End Sub

    Private Sub ExitToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ExitToolStripMenuItem.Click
        Application.Exit()
    End Sub

    Private Sub ClearToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ClearToolStripMenuItem.Click
        txtFileTypes.Text = ""
    End Sub

    Private Sub VisualStudioToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles VisualStudioToolStripMenuItem.Click
        AddFileTypes("sln,csproj,vbproj")
    End Sub

    Private Sub AddFileTypes(typ As String)
        If (txtFileTypes.Text <> "") Then
            txtFileTypes.Text += ","
        End If
        txtFileTypes.Text += typ
    End Sub

    Private Sub OfficeToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles OfficeToolStripMenuItem.Click
        AddFileTypes("doc,docx,xls,xlsx,ppt,pptx")
    End Sub

    Private Sub OfficeProToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles OfficeProToolStripMenuItem.Click
        AddFileTypes("doc,docx,xls,xlsx,ppt,pptx,pub,mdb,accb")
    End Sub

    Private Sub TextToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles TextToolStripMenuItem.Click
        AddFileTypes("txt")
    End Sub

    Private Sub DocDocxToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles DocDocxToolStripMenuItem.Click
        AddFileTypes("doc,docx")
    End Sub

    Private Sub MSExcelToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles MSExcelToolStripMenuItem.Click
        AddFileTypes("xls,xlsx")
    End Sub

    Private Sub ImageToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ImageToolStripMenuItem.Click
        AddFileTypes("bmp, png, jpg, jpeg, gif, tif, tiff")
    End Sub

    Private Sub PdfToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles PdfToolStripMenuItem.Click
        AddFileTypes("pdf")
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        DataGridView1.Sort(DataGridView1.Columns("RowTag"), System.ComponentModel.ListSortDirection.Ascending)
    End Sub

    Private Sub AboutToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles AboutToolStripMenuItem.Click
        AboutBox1.ShowDialog()
    End Sub

    Private Sub CopyPathToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles CopyPathToolStripMenuItem.Click
        Dim CurrentRow As DataGridViewRow = DataGridView1.CurrentRow
        Dim path As String = CurrentRow.Cells("RowPath").Value
        Clipboard.SetText(path)
    End Sub

    'Could use these paths in a later version
    Dim mydoc = My.Computer.FileSystem.SpecialDirectories.MyDocuments
    Dim mymusic = My.Computer.FileSystem.SpecialDirectories.MyMusic
    Dim myPictures = My.Computer.FileSystem.SpecialDirectories.MyPictures
    Dim mydesktop = My.Computer.FileSystem.SpecialDirectories.Desktop

    Private Sub OpenDircetoryInFileExplorerToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles OpenDircetoryInFileExplorerToolStripMenuItem.Click
        Dim CurrentRow As DataGridViewRow = DataGridView1.CurrentRow
        'Determine if we can drill into this
        Dim access As String = CurrentRow.Cells("RowAccessState").Value
        If access = "Access Denied" Then
            Beep()
            Return
        End If
        Dim path As String = CurrentRow.Cells("RowPath").Value
        Process.Start("Explorer.exe", path)
        'Clipboard.SetText(path)
    End Sub

    Private Sub OpenDirectoryAboveInFileExplorerToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles OpenDirectoryAboveInFileExplorerToolStripMenuItem.Click
        Dim CurrentRow As DataGridViewRow = DataGridView1.CurrentRow
        'Determine if we can drill into this
        Dim access As String = CurrentRow.Cells("RowAccessState").Value
        If access = "Access Denied" Then
            Beep()
            Return
        End If
        Dim path As String = CurrentRow.Cells("RowPath").Value
        'Ref: http://support.microsoft.com/kb/152457
        path = "/e, /select, " + path
        Process.Start("Explorer.exe", path)
    End Sub

    Function GetExtension(path As String) As String
        Dim i As Integer = path.LastIndexOf(".")
        If i > 0 Then
            Return path.Substring(i)
        End If
        Return ""
    End Function
    Function GetFilename(path As String) As String
        If (path.Substring(path.Length - 1) = "\") Then
            path = path.Substring(0, (path.Length - 1))
        End If
        Dim i As Integer = path.LastIndexOf("\")
        If i > 0 Then
            Return path.Substring(i + 1)
        End If
        Return path
    End Function

    Public FilteredListOfFilenames As List(Of String)
    Public FilteredListOfFilepaths As List(Of String)

    Private Function RecurseToGetSubDirFilesUsingFilterMask(dir As String, dirsmask As String, filenamemask As String) As List(Of FileInfo)
        Dim dirInfo As DirectoryInfo = My.Computer.FileSystem.GetDirectoryInfo(dir)
        Dim fileList As New List(Of FileInfo)()
        fileList.AddRange(dirInfo.GetFiles(filenamemask))
        Try
            For Each ChildDirectory As String In My.Computer.FileSystem.GetDirectories(dir, FileIO.SearchOption.SearchTopLevelOnly)
                Try
                    Dim tempList As List(Of FileInfo) = RecurseToGetSubDirFilesUsingFilterMask(ChildDirectory, dirsmask, filenamemask)
                    fileList.AddRange(tempList)
                Catch ex As Exception
                    Dim i As Integer = 0
                    'Continue with other children if there is an error
                End Try
            Next
        Catch ex As Exception
            MessageBox.Show("Error in GetSubDirFiles()")
            'Possible access error
        End Try
        Return fileList
    End Function

    Private Sub GetListOfFilesUniqueToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles GetListOfFilesUniqueToolStripMenuItem.Click
        Dim CurrentRow As DataGridViewRow = DataGridView1.CurrentRow

        'Determine if we can drill into this
        Dim access As String = CurrentRow.Cells("RowAccessState").Value
        If access = "Access Denied" Then
            Beep()
            Return
        End If

        'Determine if we can drill into this
        Try
            Dim numFilesStr As String = CurrentRow.Cells("TotalFileCount").Value
            If CInt(numFilesStr) = 0 Then
                Beep()
                Return
            End If
        Catch ex As Exception
            Beep()
            Return
        End Try


        Dim path As String = CurrentRow.Cells("RowPath").Value

        'Get all all files that fit the filename mask
        Dim filenameMask As String = txtFilenameMask.Text + ".*"
        If filenameMask = ".*" Then filenameMask = "*.*"

        'Default Directory mask to *.*
        Dim DirsMask As String = txtDirsMask.Text
        'If mask is blank then make *
        If (DirsMask = "") Then DirsMask = "*"
        'If Mask doesn't any have wildstars or double quotes then append then  * That way 
        If Not (DirsMask.Contains("*") Or DirsMask.Contains("?") Or DirsMask.Contains("""")) Then DirsMask += "*"
        'If Mask has " then remove them now. That way can just search for a specific dir but must be in double  quotes
        If DirsMask.Contains("""") Then DirsMask = DirsMask.Replace("""", "")

        Dim fileList As List(Of FileInfo) = RecurseToGetSubDirFilesUsingFilterMask(path, DirsMask, filenameMask)
        Dim FilenameListStr() As String = Nothing
        Dim FilepathListStr() As String = Nothing
        Dim filetypesList As New List(Of String)

        'No file found ?
        If (fileList.Count = 0) Then
            Beep()
            Return
        End If


        If (Trim(txtFileTypes.Text) <> "") Then
            'Apply the file type filter

            Dim sep() As Char = ",".ToCharArray()
            Dim filetypesStr() As String = Trim(txtFileTypes.Text).Split(sep)

            Dim varl = From xn As String In filetypesStr Where Trim(xn.Replace(".", "")) <> "" Select "." + Trim(xn.Replace(".", ""))
            filetypesList = varl.ToList()

            'Now get those file types
            If (filetypesList.Count <> 0) Then
                Try
                    Dim var = From finfo As System.IO.FileInfo In fileList Where filetypesList.Contains(finfo.Extension) Select finfo.Name
                    FilenameListStr = var.ToArray()
                    Dim var2 = From finfo As System.IO.FileInfo In fileList Where filetypesList.Contains(finfo.Extension) Select finfo.FullName
                    FilepathListStr = var2.ToArray()
                Catch ex As Exception
                    MessageBox.Show("Error in GetListOfFilesUniqueToolStripMenuItem_Click-1.1()", "FileSystemExplorer", MessageBoxButtons.OK, MessageBoxIcon.Error)
                    Return
                End Try
            End If
        End If

        If (filetypesList.Count = 0) Then
            Try
                ' The following Linq code essentially works but can cause errors with some syste etc file (path too long etc)
                ' It is therefore implemented following as loops etc
                'Dim var = From finfo As System.IO.FileInfo In fileList Select finfo.Name
                ' FilenameListStr = var.ToArray()
                ' Dim var2 = From finfo As System.IO.FileInfo In fileList Select finfo.FullName
                'FilepathListStr = var2.ToArray()

                ReDim FilenameListStr(fileList.Count)
                ReDim FilepathListStr(fileList.Count)



                For i As Integer = 0 To fileList.Count - 1
                    Dim filename As String = Nothing
                    Dim filepath As String = Nothing
                    Try
                        filename = fileList(i).Name
                        filepath = fileList(i).FullName
                        If Not ((filename Is Nothing) Or (filepath Is Nothing) Or (filename = "") Or (filepath = "")) Then
                            FilenameListStr(i) = filename
                            FilepathListStr(i) = filepath
                        Else
                            'Any issues make teh entry blank
                            FilenameListStr(i) = ""
                            FilepathListStr(i) = ""
                        End If
                    Catch ex As Exception
                        'Any issues make the entry blank
                        FilenameListStr(i) = """"
                        FilepathListStr(i) = """"
                    End Try
                Next
            Catch ex As Exception
                MessageBox.Show("Error in GetListOfFilesUniqueToolStripMenuItem_Click-1.2()", "FileSystemExplorer", MessageBoxButtons.OK, MessageBoxIcon.Error)
                Return
            End Try
        End If

        Try
            'Remove any blank entries
            Dim var10 = From fname As String In FilenameListStr Where fname <> "" Select fname
            FilenameListStr = var10.ToArray()
            Dim var11 = From fpath As String In FilepathListStr Where fpath <> "" Select fpath
            FilepathListStr = var11.ToArray()
        Catch ex As Exception
            MessageBox.Show("Error in GetListOfFilesUniqueToolStripMenuItem_Click-1.3()", "FileSystemExplorer", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Return
        End Try

        'No files found ?
        If (fileList.Count = 0) Then
            Beep()
            Return
        Else
            Try
                FilteredListOfFilenames = New List(Of String)
                FilteredListOfFilenames.AddRange(FilenameListStr.Distinct)
                FilteredListOfFilepaths = New List(Of String)
                FilteredListOfFilepaths.AddRange(FilepathListStr.Distinct)

                frmGetFiles.path = path
                frmGetFiles.filetypes = filetypesList
                frmGetFiles.FilenamesList = FilteredListOfFilenames
                frmGetFiles.FilePathsList = FilteredListOfFilepaths
                frmGetFiles.ShowDialog()

            Catch ex As Exception
                MessageBox.Show("Error in GetListOfFilesUniqueToolStripMenuItem_Click-2.0()", "FileSystemExplorer", MessageBoxButtons.OK, MessageBoxIcon.Error)
                Return
            End Try
        End If
    End Sub

End Class
